/*
  Author: xiaokai 
        - email: xiaokai.c@foxmail.com 
        - gitee: https://gitee.com/xiaokaiC
*/


#include "calculator.h"
#include "seq_stack.h"
#include "stdio.h"
#include "stdlib.h"

char *ops_cache[MAXSIZE*sizeof(char)];
char *vals_cache[MAXSIZE*sizeof(double)];


seq_stack_t ops  = {
    .top = 0,
	  .cell_len = sizeof(char),
	  .max_len = MAXSIZE,
	  .data = (unsigned char *)ops_cache	  
};

seq_stack_t vals  = {
    .top = 0,
	  .cell_len = sizeof(double),
	  .max_len = MAXSIZE,
	  .data = (unsigned char *)vals_cache	  
};

void ops_push(char c) {
   seq_stack_push(&ops,(void *)&c);
}

char ops_pop(void) {
	 char c;
   seq_stack_pop(&ops,(void *)&c);
	 return c;
}


char ops_top(void) {
	 char c;
   seq_stack_top(&ops,(void *)&c);
	 return c;
}

void vals_push(double d) {
   seq_stack_push(&vals,(void *)&d);
} 

double vals_pop(void) {
   double d;
	 seq_stack_pop(&vals,(void *)&d);
	 return d;
}

int getPriority(char ch)
{
	
	if (ch == '(') return 1;
	else if (ch == '+' || ch == '-') return 2;
	else if (ch == '*' || ch == '/') return 3;
	else return 4;
}


void compute()
{
	char c;
	double a ,b,d;
	c = ops_pop();

	a = vals_pop();
	b = vals_pop();
	if (c=='*') d = b * a;
	else if (c=='/') d = b / a;
	else if (c=='+') d = b + a;
	else if (c=='-') d = b - a;
	else printf("never occur!");
	vals_push(d);
}


double Compute_infix(char* s)
{
	  char buf[20];
	  unsigned char i;
    while(*s){
			
			if (*s == '(') {
			   ops_push(*s);
				 s++;
			}          
			else if (*s == '*' || *s == '+' ||*s == '-' || *s == '/') {
				
				 if (is_seq_stack_empty(&ops)) {
				 	  ops_push(*s);
				 } else {
				 		while(!is_seq_stack_empty(&ops)){
               char op = ops_top();
				       if(getPriority(op) >= getPriority(*s)){
					        compute();
				       }else{
						      break;
					     }
				    }
				    ops_push(*s);
				 }
				 s++;

			}
			else if(*s == ')') {
			  char op = ops_top();
				while (op != '(') {
				    compute();
				    op = ops_top();
			  }
				ops_pop();
				s++;
			}
			else {
			   for (i = 0;(*s >= '0' && *s <= '9') || *s == '.'; s++,i++){
				   buf[i] = *s;
				 }
				 buf[i] = 0;
				 double value = atof(buf);
				 vals_push(value);
			}
		}
	  while(!is_seq_stack_empty(&ops)){
		   compute();
	  }
		return vals_pop();
}



